<!--响应式布局画布(暂时还没实现)-->

<template>
  <div id="ReactiveLayoutContainer" style="width: 100%; height: 100%; overflow: auto; padding-top: 33px;">

    <div class="canvas-toolbar">
      <ButtonGroup class="m-r-5px" size="small" shape="circle">
        <Button type="primary" @click="zoomIn('zoomArea')">放大</Button>
        <Button type="primary" @click="zoomOut('zoomArea')">缩小</Button>
        <Button type="primary" @click="zoomReset('zoomArea')">还原</Button>
        <Button type="default">缩放比例：{{zoomValue.toFixed(1)}}</Button>
      </ButtonGroup>
    </div>

    <div id="zoomArea" style="width: 100%; height: 100%;">
      <div id="ReactiveLayout" class="reactive-layout-canvas"
           :style="Object.assign({
            backgroundColor: layout.layoutConfigData.backgroundColor,
            width: layout.layoutConfigData.width + layout.layoutConfigData.widthPixelUnit,
            height: layout.layoutConfigData.height + layout.layoutConfigData.heightPixelUnit,

            backgroundImage: layout.layoutConfigData.imageRelativePath ? 'url('+canvasBackgroundImageSrc+')': '',
            backgroundRepeat: layout.layoutConfigData.imageRelativePath ? layout.layoutConfigData.imageRepeat: '',
            backgroundSize: layout.layoutConfigData.imageRelativePath ? layout.layoutConfigData.imageSize: ''
           }, $PnUtil.cssToVueStyleObj(layout.layoutConfigData.customStyleCode))" @click.stop="layoutCanvasClick">

        <h1 v-if="gridLayoutItems.length == 0" class="message">试试打开组件库，拖拽个布局块进来吧！</h1>

        <grid-layout
            :layout.sync="gridLayoutItems"
            :col-num="12"
            :row-height="30"
            :is-draggable="layout.layoutConfigData.draggable"
            :is-resizable="layout.layoutConfigData.resizable"
            :is-mirrored="false"
            :vertical-compact="true"
            :responsive="layout.layoutConfigData.responsive"
            :margin="[layout.layoutConfigData.gridItemMargin, layout.layoutConfigData.gridItemMargin]"
            :use-css-transforms="false"
            @layout-updated="gridLayoutUpdatedEvent">
          <grid-item class="reactive-grid-item"
                     :class="buildLayoutItemClassObj(layoutItem)"
                     v-for="layoutItem in gridLayoutItems"
                     :style="{display: layoutItem.display}"
                     :x="layoutItem.x"
                     :y="layoutItem.y"
                     :w="layoutItem.w"
                     :h="layoutItem.h"
                     :i="layoutItem.i"
                     :key="layoutItem.i">
            <div class="reactive-layout-item"
                 :id="layoutItem.i"
                 :data-id="layoutItem.i"
                 :style="{
                   backgroundColor: layoutItem.backgroundColor,
                   borderWidth: layoutItem.borderWidth + 'px',
                   borderStyle: layoutItem.borderStyle,
                   borderColor: layoutItem.borderColor,
                   borderTopLeftRadius: layoutItem.borderTopLeftRadius + 'px',
                   borderTopRightRadius: layoutItem.borderTopRightRadius + 'px',
                   borderBottomLeftRadius: layoutItem.borderBottomLeftRadius + 'px',
                   borderBottomRightRadius: layoutItem.borderBottomRightRadius + 'px',

                   padding: layoutItem.padding + 'px'
                 }"
                 @click.stop="layoutItemClick(layoutItem)"
                 @contextmenu.prevent="layoutItemContextMenu(true, $event)">
              <FuncCompContainer :location="layoutItem.i" :defaultText="layoutItem.i">
                <component :is="layoutItem.component.name" :location="layoutItem.i"></component>
              </FuncCompContainer>
            </div>
          </grid-item>
        </grid-layout>

        <!--布局块右键菜单-->
        <Card ref="layoutItemContextMenu" :padding="0" shadow
              style="position: fixed; z-index: 999; display: none; border-radius: 0px;">
          <div>
            <CellGroup @on-click="layoutItemContextMenuClick">
              <Cell name="menu_delLayoutItem" style="color: #ed4014;"><Icon type="md-trash"/> 删除布局块</Cell>
              <Cell name="menu_unbindComponent"><Icon type="md-close" /> 解除关联组件</Cell>
            </CellGroup>
          </div>
        </Card>

      </div>
    </div>
  </div>
</template>

<script>

  import VueGridLayout from 'vue-grid-layout';
  import CanvasDesignerMixin from '@/mixin/CanvasDesignerMixin';

  import { createHelpers } from 'vuex-map-fields';

  const { mapFields } = createHelpers({
    getterType: 'designer/getField',
    mutationType: 'designer/updateField',
  });

  export default {
    name: 'ReactiveLayoutCanvas',
    mixins: [CanvasDesignerMixin],
    components: {
      GridLayout: VueGridLayout.GridLayout,
      GridItem: VueGridLayout.GridItem
    },
    data() {
      return {
        gridLayoutItems: [],

        keepCtrl: false,
      }
    },
    mounted() {
      this.buildGridLayoutItems();
      this.registerCanvasDrop();
      this.registerLayoutItemDrop();
      this.registerKeyDownAndUp();
    },
    methods: {

      /************************** GridLayout相关事件 **************************/

      gridLayoutUpdatedEvent: function (newGridLayoutData) {

        let tmpLayout = this.$PnUtil.deepClone(this.layout);
        tmpLayout.layoutItems.forEach(layoutItem => {
          this.gridLayoutItems.forEach(gridLayoutItem => {
            if(layoutItem.id == gridLayoutItem.i) {
              layoutItem.layoutItemConfigData.x = gridLayoutItem.x;
              layoutItem.layoutItemConfigData.y = gridLayoutItem.y;
              layoutItem.layoutItemConfigData.w = gridLayoutItem.w;
              layoutItem.layoutItemConfigData.h = gridLayoutItem.h;
            }
          })
        });

        this.$store.commit('designer/setLayout', tmpLayout)
      },

      /************************** GridLayout相关事件 end **************************/

      buildGridLayoutItems () {
        this.gridLayoutItems = [];
        let tmpLayoutItems =  Object.assign([], this.layout.layoutItems);
        tmpLayoutItems.forEach(item => {
          let obj = Object.assign({
            i: item.id
          }, item.layoutItemConfigData);
          obj.component = item.component;

          this.gridLayoutItems.push(obj)
        });
      },

      /************************** 布局块右键菜单相关处理 **************************/

      layoutItemContextMenu (enabled, event) {
        if (enabled) {
          this.$refs.layoutItemContextMenu.$el.style.display = 'block';
          this.$refs.layoutItemContextMenu.$el.style.left = (event.x + 5) + 'px';
          this.$refs.layoutItemContextMenu.$el.style.top = (event.y + 5) + 'px';
        }else {
          this.$refs.layoutItemContextMenu.$el.style.display = 'none';
        }
      },

      layoutItemContextMenuClick (name) {
        let tmpLayoutItemId = this.currentSelectLayoutItemId;
        let tmpLayoutItemIds = this.currentSelectLayoutItemIds.concat();
        // 删除布局块
        if (name == 'menu_delLayoutItem') {
          this.$Modal.confirm({
            title: '提醒',
            content: '确认删除所选中的布局块吗？',
            onOk: () => {
              let layoutItemIds = [];
              if(tmpLayoutItemIds.length > 0) {
                layoutItemIds = tmpLayoutItemIds
              }else {
                layoutItemIds.pushNoRepeat(tmpLayoutItemId)
              }
              layoutItemIds.forEach(id => {
                this.$store.commit('designer/deleteLayoutItem', id);
                this.$store.commit('designer/setRightSidebarLayoutItemConfigFormName', '');
                this.$store.commit('designer/setCurrentSelectLayoutItemId', '');
                this.$store.commit('designer/setCurrentSelectLayoutItemIds', []);
                this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '')
              });
            }
          });
        }
        // 解绑关联组件
        else if (name == 'menu_unbindComponent') {
          this.$Modal.confirm({
            title: '提醒',
            content: '确认解除所选中布局块的关联组件吗？',
            onOk: () => {
              let layoutItemIds = [];
              if(tmpLayoutItemIds.length > 0) {
                layoutItemIds = tmpLayoutItemIds
              }else {
                layoutItemIds.pushNoRepeat(tmpLayoutItemId)
              }
              layoutItemIds.forEach(id => {
                this.$store.commit('designer/deleteComponentByLayoutItemId', id);
                this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '')
              });

            }
          });
        }
      },

      /************************** 布局块右键菜单相关处理 end **************************/

      registerKeyDownAndUp () {
        let _this = this;

        $(document).unbind('keydown');
        $(document).unbind('keyup');

        $(document).bind("keydown", function(e) {

          let keyCode = event.keyCode || event.which || event.charCode;
          let ctrlKey = event.ctrlKey || event.metaKey;

          // ctrl + a 全选组合键
          if(ctrlKey && keyCode == 65) {
            event.preventDefault();
            let ids = [];
            _this.layout.layoutItems.forEach(item => {
              ids.pushNoRepeat(item.id)
            });
            _this.$store.commit('designer/setCurrentSelectLayoutItemIds', ids)
          }

          if(_this.$PnUtil.isMac()) {
            if(e.keyCode == 91) { // Command键

              _this.keepCtrl = true;
              if(_this.currentSelectLayoutItemId) {
                let tmpIds = _this.currentSelectLayoutItemIds.concat();
                tmpIds.pushNoRepeat(_this.currentSelectLayoutItemId);
                _this.$store.commit('designer/setCurrentSelectLayoutItemIds', tmpIds)
              }
            }
          }else if(_this.$PnUtil.isWindows()) {
            if(e.keyCode == 17) { // Ctrl键
              _this.keepCtrl = true;
              if(_this.currentSelectLayoutItemId) {
                let tmpIds = _this.currentSelectLayoutItemIds.concat();
                tmpIds.pushNoRepeat(_this.currentSelectLayoutItemId);
                _this.$store.commit('designer/setCurrentSelectLayoutItemIds', tmpIds)
              }
            }
          }

        });
        $(document).bind("keyup", function(e) {
          if(_this.$PnUtil.isMac()) {
            if(e.keyCode == 91) { // Command键
              _this.keepCtrl = false;
            }
          }else if(_this.$PnUtil.isWindows()) {
            if(e.keyCode == 17) { // Ctrl键
              _this.keepCtrl = false;
            }
          }
        });

      },

      /**
       * 注册画布放置监听
       */
      registerCanvasDrop () {
        let _this = this;

        $("#ReactiveLayout").droppable({
          accept: ".layoutItem-card",
          drop: (e, ui) => {
            _this.$store.commit('designer/addLayoutItem', this.$PnDesigner.buildReactiveLayoutItem());
          }
        });
      },

      /**
       * 注册布局块放置事件
       */
      registerLayoutItemDrop () {
        let _this = this;

        setTimeout(() => {
          // 注册布局块放置监听
          $(".reactive-layout-item").droppable({
            accept: ".comp-card",
            activeClass: "layout-item-drop-active",
            hoverClass: "layout-item-drop-hover",
            drop: (e, ui) => {
              let layoutItemId = e.target.attributes['data-id'].nodeValue;
              let compName = ui.draggable[0].attributes['data-component'].nodeValue;
              let component = {
                id: this.$PnUtil.uuid(),
                name: compName,
                compConfigData: ''
              };
              const componentsContext = require.context('../../', true, /\.vue$/);

              componentsContext.keys().forEach(fileName => {
                const componentConfig = componentsContext(fileName);

                if(componentConfig.default.name == compName) {
                  const compInst = require('../../'+fileName.slice(2, fileName.length));
                  component.compConfigData = Object.assign({}, compInst.default.attr.configDataTemp)
                }
              });

              this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '');
              this.$store.commit('designer/addComponentToLayoutItem', {
                layoutItemId: layoutItemId,
                component: component
              })
            }
          });
        }, 100)
      },

      /**
       * 画布点击事件
       */
      layoutCanvasClick () {
        this.registerKeyDownAndUp(); // 重新注册键盘监听

        this.$store.commit('designer/setCurrentSelectLayoutItemId', '');
        this.$store.commit('designer/setCurrentSelectLayoutItemIds', []);
        this.$store.commit('designer/setRightSidebarLayoutItemConfigFormName', '');
        this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '');

        setTimeout(() => {
          this.layoutItemContextMenu(false)
        }, 150)
      },

      /**
       * 布局块点击事件
       * @param layoutItem
       */
      layoutItemClick(layoutItem) {

        this.registerKeyDownAndUp(); // 重新注册键盘监听

        this.layoutItemContextMenu(false);

        // 点击布局块的时候，给布局块设置droppable的属性scope为layoutItemScope，
        // 与组件库拖拽对象的scope对应，这样组件库的拖拽对象就可以放置在当前点击的布局块里
        $(".reactive-layout-item").droppable('option', 'scope', '');
        for (let i=0; i<event.path.length; i++) {
          let s = $(event.path[i])[0].className + '';
          if (s.indexOf('reactive-layout-item') != -1) {
            $(event.path[i]).droppable('option', 'scope', 'layoutItemScope');
          }
        }

        // 判断当前是否按住了ctrl按键 或 alt按键
        if(this.keepCtrl) {
          let selectLayoutItemIds = this.currentSelectLayoutItemIds.concat();

          if(selectLayoutItemIds.indexOf(layoutItem.id) > -1) {
            for (let i=0; i<selectLayoutItemIds.length; i++) {
              if(layoutItem.i == selectLayoutItemIds[i]) {
                if(selectLayoutItemIds.length > 1) {
                  selectLayoutItemIds.splice(i, 1);
                  i--
                }
              }
            }
          }else {
            selectLayoutItemIds.pushNoRepeat(layoutItem.i);
          }
          this.$store.commit('designer/setCurrentSelectLayoutItemIds', selectLayoutItemIds);
        } else {
          if(this.$store.state.designer.currentSelectLayoutItemIds.indexOf(layoutItem.i) == -1) {
            this.$store.commit('designer/setCurrentSelectLayoutItemIds', []) // 清除ctrl选中的布局块
          }
        }

        // 如果当前点击的布局块没有关联组件，那么就清空rightSidebarFuncCompConfigFormName状态
        if (!layoutItem.component.id) {
          this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '');
        }
        this.$store.commit('designer/setRightSidebarLayoutItemConfigFormName', 'ReactiveLayoutItemForm');
        this.$store.commit('designer/setCurrentSelectLayoutItemId', layoutItem.i)
      },


      buildLayoutItemClassObj (layoutItem) {

        if (this.$store.state.designer.currentSelectLayoutItemIds.length > 0) {
          if (this.$store.state.designer.currentSelectLayoutItemIds.indexOf(layoutItem.i) > -1 &&
            this.$PnUtil.getContrastYIQ(this.layout.layoutConfigData.backgroundColor.substring(1,7)) == 'black') {
            return 'activeBlack'
          }
          if (this.$store.state.designer.currentSelectLayoutItemIds.indexOf(layoutItem.i) > -1 &&
            this.$PnUtil.getContrastYIQ(this.layout.layoutConfigData.backgroundColor.substring(1,7)) == 'white') {
            return 'activeWhite'
          }
        }else {
          if (this.$store.state.designer.currentSelectLayoutItemId == layoutItem.i &&
            this.$PnUtil.getContrastYIQ(this.layout.layoutConfigData.backgroundColor.substring(1,7)) == 'black') {
            return 'activeBlack'
          }
          if (this.$store.state.designer.currentSelectLayoutItemId == layoutItem.i &&
            this.$PnUtil.getContrastYIQ(this.layout.layoutConfigData.backgroundColor.substring(1,7)) == 'white') {
            return 'activeWhite'
          }
        }

        return ''
      },

    },
    computed: {
      ...mapFields({
        layout: 'pageMetadata.layout',
        currentSelectLayoutItemId: 'currentSelectLayoutItemId',
        currentSelectLayoutItemIds: 'currentSelectLayoutItemIds'
      }),
      canvasBackgroundImageSrc () {
        return process.env.VUE_APP_BASEPATH + '/' + this.layout.layoutConfigData.imageRelativePath
      }
    },
    watch: {
      'layout.layoutItems': [
        {
          handler: 'buildGridLayoutItems',
          deep: true
        },
        {
          handler: 'registerLayoutItemDrop'
        }
      ]
    }
  }
</script>

<style scoped>

  .reactive-layout-canvas {
    overflow: auto;
  }

  .canvas-toolbar {
    width: 100%;
    height: 33px;
    border-bottom: 1px solid #555;
    background-color: #777;
    position: fixed;
    top: 48px;
    z-index: 2;
    line-height: 31px;
    padding-left: 20px;
  }

  .reactive-layout-canvas .message {
    font-size: 2em;
    font-weight: bold;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    opacity:0.5;
    color: #fff;
  }

  .reactive-grid-item {
    cursor: default !important;
  }

  .reactive-grid-item.activeBlack {
    box-shadow: 0 0 10px #000
  }
  .reactive-grid-item.activeWhite {
    box-shadow: 0 0 10px white
  }

  .reactive-layout-item {
    width: 100%;
    height: 100%;
  }


</style>
